package com.yonsz.open.platform.client;

import cn.hutool.Hutool;
import cn.hutool.core.lang.TypeReference;
import cn.hutool.extra.mail.Mail;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.json.JSONUtil;
import com.yonsz.open.platform.constant.Constant;
import com.yonsz.open.platform.exceptions.OpenApiException;
import com.yonsz.open.platform.exceptions.OpenApiHttpException;
import com.yonsz.open.platform.model.*;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;

import java.util.List;
import java.util.Map;
/**
 * 开放接口
 */
@Setter
@Slf4j
public class OpenApiClient {
    protected String api = Constant.API;
    protected String accessToken;

    /**
     * 初始化客户端，使用正式环境接口
     * @param accessToken
     */
    public OpenApiClient(String accessToken) {
        this.accessToken = accessToken;
    }

    /**
     * 使用其他环境接口
     * @param accessToken
     * @param api
     */
    public OpenApiClient(String accessToken,String api){
        this.accessToken = accessToken;
        this.api = api;
    }

    /**
     * 获取家庭列表
     * @return
     * @throws OpenApiException
     * @throws OpenApiHttpException
     */
    public List<House> getHouseList() throws OpenApiException, OpenApiHttpException {
        OpenRequest req = new OpenRequest(Constant.HEADER_TYPE_HOUSE_LIST);
        OpenResponse res = request(req);
        return res.getResult().getHouses();
    }

    /**
     * 获取家庭下的设备列表
     * @param houseId 家庭id，从获取家庭列表中获取
     * @param withCmd  是否附带控制命令，用于离线控制
     * @return
     */

    public List<Device> getDeviceList(String houseId,boolean withCmd){
        OpenRequest req = new OpenRequest(Constant.HEADER_TYPE_LIST);
        req.setPayload(OpenRequestPayload.buildListPayload(houseId, withCmd));
        OpenResponse res = request(req);
        return res.getResult().getDevices();
    }

    /**
     * 控制设备
     * @param deviceId 设备id，从获取设备列表中获取
     * @param oper  操作
     */
    public void control(String deviceId, String oper){
        control(deviceId,oper,null);
    }

    /**
     * 控制设备， 带控制值，比如空调温度设置，灯光亮度设置
     * @param deviceId
     * @param oper
     * @param value
     */
    public void control(String deviceId, String oper, String value){
        OpenRequest req = new OpenRequest(Constant.HEADER_TYPE_CONTROL);
        req.setPayload(OpenRequestPayload.buildControlPayload(deviceId, oper,value));
        request(req);
    }

    /**
     * 获取设备状态
     * @param deviceId
     * @return
     */
    public Map<String,Object> getStatus(String deviceId){
        OpenRequest req = new OpenRequest(Constant.HEADER_TYPE_STATUS);
        req.setPayload(OpenRequestPayload.buildStatusPayload(deviceId));
        OpenResponse res = request(req);
        return res.getResult().getStatus();
    }

    /**
     * 获取情景模式列表
     * @param houseId
     * @return
     */
    public List<Mode> getModeList(String houseId){
        OpenRequest req = new OpenRequest(Constant.HEADER_TYPE_MODE_LIST);
        req.setPayload(OpenRequestPayload.buildModeListPayload(houseId));
        OpenResponse res = request(req);
        return res.getResult().getModes();
    }

    /**
     * 执行情景模式
     * @param modeId
     * @param houseId
     */
    public void modeControl(String modeId,String houseId){
        OpenRequest req = new OpenRequest(Constant.HEADER_TYPE_MODE_CONTROL);
        req.setPayload(OpenRequestPayload.buildModeControlPayload(modeId,houseId));
        request(req);
    }


    public  OpenResponse request(OpenRequest request){
        HttpResponse response = HttpRequest.post(this.api)
                .header("Authorization","Bearer "+ accessToken)
                .body(JSONUtil.toJsonStr(request)).execute();
        if(response.getStatus()!=200){
            throw new OpenApiHttpException(response.getStatus(),response.body());
        }
        String body =response.body();
        log.debug("api 请求 : {}",body);
        OpenResponse res = JSONUtil.toBean(body, new TypeReference<OpenResponse>() {}, false);
        if(!res.getSuccess()){
            throw new OpenApiException(res);
        }
        return res;
    }
}
